from pyglet.gl import *
import data
from math import *
import random
from particles import *

class GameObject:
    MAP = "MAP"
    HERO = "HERO"
    ENEMY = "ENEMY"
    ENEMY1 = "ENEMY1"
    ENEMY2 = "ENEMY2"
    PICKUP = "PICKUP"
    OBJECT = "OBJECT"
    POWERUP_S = "POWERS"    #speed
    POWERUP_I = "POWERI"    #invulnerability
    POWERUP_B = "POWERB"    #nuke every enemy object
    POWERUP_M = "POWERM"    #magnetic ability

    def __init__(self, r = 15):
        self.pos = (100, 100)
        self.r = r 
        self.vel = (10, 10)
        self.bounds = (800, 600)
        self.type = GameObject.OBJECT

    def update(self, dt):
        pos = (self.pos[0] + self.vel[0], self.pos[1] + self.vel[1])
        #set the velocity for bounce
        pvel = self.vel
        if pos[0]-self.r < 0 or pos[0]+self.r > self.bounds[0]:
            self.vel = (-self.vel[0], self.vel[1])
        if pos[1]-self.r < 0 or pos[1]+self.r > self.bounds[1]:
            self.vel = (self.vel[0], -self.vel[1])
        if pvel == self.vel:
            self.pos = pos

    def render(self):
        glBegin(GL_POLYGON)
        glTexCoord2f(0, 0)
        glVertex2f(self.pos[0]-self.r, self.pos[1]-self.r)
        glTexCoord2f(0, 1)
        glVertex2f(self.pos[0]-self.r, self.pos[1]+self.r)
        glTexCoord2f(1, 1)
        glVertex2f(self.pos[0]+self.r, self.pos[1]+self.r)
        glTexCoord2f(1, 0)
        glVertex2f(self.pos[0]+self.r, self.pos[1]-self.r)
        glEnd()

    def collision(self, obj):
        x = self.pos[0] - obj.pos[0]
        y = self.pos[1] - obj.pos[1]
        d = sqrt(x*x + y*y)
        if d < self.r + obj.r:
            return True
        return False

class OutEnemy(GameObject):
    def __init__(self, r):
        GameObject.__init__(self)
        self.type = GameObject.ENEMY1
        self.wr = r #radius of the world outside
        self.angle = random.randint(0, 360) 
        self.adt = random.choice([-1,1])
        self.pos = (self.wr, 0)
        self.update(0)

    def render(self):
        glBindTexture(GL_TEXTURE_2D, data.e1_image.id)

        glPushMatrix()
        glTranslatef(self.pos[0], self.pos[1], 0)
        glRotatef(self.angle, 0, 0, 1)
        glTranslatef(-self.pos[0], -self.pos[1], 0)
        GameObject.render(self)
        glPopMatrix()


    def update(self, dt):
        self.angle += self.adt;
        self.angle %= 360
        rads = self.angle * 2 * 3.14 / 360
        self.pos = (self.wr * cos(rads), self.wr*sin(rads))

class InEnemy(GameObject):
    def __init__(self):
        GameObject.__init__(self, 15)
        self.type = GameObject.ENEMY
        self.r_angle = 0
        self.texid = data.e2_image.id

    def update(self, dt):
        self.r_angle -= 60*dt
        self.r_angle %= 360

    def render(self):
        glPushMatrix()
        glTranslatef(self.pos[0], self.pos[1], 0)
        glRotatef(self.r_angle, 0, 0, 1)
        glTranslatef(-self.pos[0], -self.pos[1], 0)
        glColor3f(1, 1, 1)
        glBindTexture(GL_TEXTURE_2D, self.texid)
        GameObject.render(self)
        glPopMatrix()

class MoveEnemy(InEnemy):
    SPEED = 2;
    def __init__(self, r, h):
        InEnemy.__init__(self) 
        self.r = 20
        self.hero = h
        self.pos = (0, 0)
        self.getVel()
        self.texid = data.e3_image.id
        self.wr = r
        self.type = GameObject.ENEMY2

    def getVel(self):
        h = self.hero
        (vx, vy) = (h.pos[0]-self.pos[0], h.pos[1]-self.pos[1])
        vel = (vx/sqrt(vx*vx+vy*vy), vy/sqrt(vx*vx+vy*vy)) 
        self.vel = (vel[0] * MoveEnemy.SPEED, vel[1] * MoveEnemy.SPEED)

    def update(self, dt):
        self.r_angle += 20
        self.r_angle %= 360
        #if self.pos[0] * self.pos[0] + self.pos[1] * self.pos[1] > self.wr * self.wr:
        self.getVel()
        p = (self.pos[0] + self.vel[0], self.pos[1] + self.vel[1])
        self.pos = p

class PickUp(GameObject):
    def __init__(self):
        GameObject.__init__(self, 10)
        self.type = GameObject.PICKUP
        self.vel = (0, 0)
        self.r_angle = 0
        self.texid = data.pickup_image.id

    def update(self, dt):
        self.r_angle += 60 * dt;
        self.r_angle %= 360

    def render(self):
        glPushMatrix()
        glTranslatef(self.pos[0], self.pos[1], 0)
        glRotatef(self.r_angle, 0, 0, 1)
        glTranslatef(-self.pos[0], -self.pos[1], 0)
        glBindTexture(GL_TEXTURE_2D, self.texid)
        GameObject.render(self)
        glPopMatrix()


def GetColor(type):
    if type == GameObject.POWERUP_S:
        return (0.38, 0.66, 1)  #blue
    elif type == GameObject.POWERUP_I:
        return (247/255.0, 249/255.0, 64/255.0)  #yellow
    elif type == GameObject.POWERUP_B:
        return (0.61, 158/255.0, 253/255.0) #maroon

class PowerUp(PickUp):
    TTL = 150
    def __init__(self, type = GameObject.POWERUP_S, pos = (0, 0)):
        PickUp.__init__(self)
        self.r = 15
        self.texid = data.powerup_image.id
        self.color = GetColor(type)
        self.type = type
        self.pos = pos #(0, random.randint(-100, 100))
        self.timer = PowerUp.TTL

    def update(self, dt):
        PickUp.update(self, dt)
        self.timer -= 1

    def render(self):
        glColor4f(self.color[0], self.color[1], self.color[2], 1)
        PickUp.render(self)
        glColor4f(1, 1, 1, 1)


class Hero(GameObject):
    COLOR = (112/255.0, 198/255.0, 74/255.0)
    P_TIME = 200    #how long the powerup lasts
    P_WARNING = 10  #warning for powerup end
    def __init__(self, r):
        GameObject.__init__(self)
        self.bound_r = r
        self.type = GameObject.HERO
        self.smoke = []
        self.add_smoke = 0
        self.color = Hero.COLOR
        self.timer = 0 
        self.powerup = None
        self.speed = 5

    def render(self):
        glBindTexture(GL_TEXTURE_2D, data.hero_image.id)
        glColor3f(self.color[0], self.color[1], self.color[2])
        GameObject.render(self)
        for smoke in self.smoke:
            smoke.render()
        glColor4f(1, 1, 1, 1)

    def setPowerUp(self, p):
        self.color = p.color
        self.powerup = p.type
        self.timer = Hero.P_TIME
        if self.powerup == GameObject.POWERUP_S:
            self.vel = (self.vel[0]/self.speed, self.vel[1]/self.speed)
            self.speed = 10 
            self.setVel(self.vel)
    
    def setVel(self, vel):
        self.vel = (self.speed * vel[0], self.speed * vel[1])

    def noPowerUp(self):
        self.color = Hero.COLOR
        self.powerup = None
        self.timer = 0
        self.vel = (self.vel[0]/self.speed, self.vel[1]/self.speed)
        self.speed = 5 
        self.setVel(self.vel)

    def update(self, dt):
        self.timer -= 1
        if self.powerup:
            if self.timer == 0:
                self.smoke.append(Particle(self.pos, (0, 0), data.powerup_image.id))
                self.noPowerUp()
            #elif self.timer < Hero.P_WARNING:
        pos = (self.pos[0] + self.vel[0], self.pos[1]+ self.vel[1])
        if pos[0]*pos[0] + pos[1]*pos[1] > self.bound_r * self.bound_r:
            self.vel = (0, 0)
            self.add_smoke = 0
        else:
            self.pos = pos
            if not self.vel == (0, 0):
                self.add_smoke+= 1
            if self.add_smoke > 2:
                p1 = (self.pos[0] - 4*self.vel[0], self.pos[1]-2*self.vel[1])
                p2 = (self.pos[0] - self.vel[0], self.pos[1]-4*self.vel[1])
                p3 = (self.pos[0] -2*self.vel[0], self.pos[1]-self.vel[1])
                self.smoke.append(Particle(random.choice([p1, p2, p3]), (0, 0), data.smoke_image.id))
                self.add_smoke = 0
        for smoke in self.smoke:
            smoke.update(dt)
            if smoke.size > 2 * Particle.MaxSize:
                self.smoke.remove(smoke)
